<?php

class Workset_Db_Table extends Zend_Db_Table {

    protected static $_instances = array();

    protected $_rowClass = 'Workset_Db_Table_Row';

    protected $_rowsetClass = 'Workset_Db_Table_Rowset';

    /**
     * @static
     * @param   $class
     * @param   array $config
     * @param   $definition
     * @return  Workset_Db_Table
	 *
	 * Multiton implementation
     *
     * Возвращает объект таблицы
     */
    static function getStaticTable($class = null, $config = array(), $definition = null) {
        if ($config instanceof Zend_Config) {
            $config = $config->toArray();
        }

        $key = $class = $class === null ? __CLASS__ : (string)$class;

        if (!empty($config)) {
            if (is_array($config)) {
                ksort($config);
            }
            $key .= serialize($config);
        }

        if (!isset(self::$_instances[$key])) {
            $instance = new $class($config);
            if ($definition instanceof Zend_Db_Table_Definition) {
                $instance->setDefinition($definition);
            }
            self::$_instances[$key] = $instance;
        }
        //@todo если объект изменен из вне (через set-ры)
        else {}

        return self::$_instances[$key];
    }

    /**
     * @return string
     *
     * Возвращает ключ кеша метаданных таблицы
     */
    function getMetadataCacheId() {
        $dbConfig = $this->_db->getConfig();

        // Define the cache identifier where the metadata are saved
        $cacheId = md5( // port:host/dbname:schema.table (based on availabilty)
            (isset($dbConfig['options']['port']) ? ':'.$dbConfig['options']['port'] : null)
            . (isset($dbConfig['options']['host']) ? ':'.$dbConfig['options']['host'] : null)
            . '/'.$dbConfig['dbname'].':'.$this->_schema.'.'.$this->_name
        );

        return $cacheId;
    }

    /**
     * @return null
     *
     * Очищает кеш метаданных таблицы
     */
    function clearMetadataCache() {
        $cache = $this->getMetadataCache();
        if ($cache) {
            $cacheId = $this->getMetadataCacheId();
            return $cache->remove($cacheId);
        }
    }

    /**
     * @param  $where
     * @param  $order
     * @param  $count
     * @param  $offset
     * @return Zend_Db_Table_Rowset_Abstract
     *
     * Возвращает выборку из БД в виде объекта Zend_Db_Table_Rowset_Abstract
     */
    function fetchAll($where = null, $order = null, $count = null, $offset = null, $countRows = false) {
        $select = $this->prepareSelect($where, $order, $count, $offset);
        return parent::fetchAll($select);
    }

    /**
     * @param  $where
     * @param  $order
     * @param  $count
     * @param  $offset
     * @return array
     *
     * Вовзращает выборку из БД в виде массива
     */
    function fetchArray($where = null, $order = null, $count = null, $offset = null) {
        $select = $this->prepareSelect($where, $order, $count, $offset);
        return $this->_fetch($select);
    }

    function fetchRow($where = null, $order = null) {
        $select = $this->prepareSelect($where, $order);
        return parent::fetchRow($select);
    }

    /**
     * @param  $where
     * @param  $order
     * @param  $count
     * @param  $offset
     * @return Zend_Db_Table_Select
     *
     * Формирует объект Select для таблицы
     */
    function prepareSelect($where = null, $order = null, $count = null, $offset = null, $alias = null) {
        if (!($where instanceof Zend_Db_Table_Select)) {
            $select = $this->select();

            if ($where !== null) {

                $where = (array) $where;
                $group = null;

                if (isset($where['GROUP'])) {
                    $group = $where['GROUP'];
                    unset($where['GROUP']);
                }

                if (null !== $alias) {
                    if (true === $alias) {
                        $alias = 'm';
                    } elseif (!is_string($alias)) {
                        throw new Zend_Db_Table_Exception('Invalid table alias');
                    }
                }

                foreach ($where as $key => $value) {

                    if ($group) {
                        $value = $this->_groupWhere((array)$value, $group == 'OR');
                        $key = 0;
                    } elseif (is_string($key) && is_array($value)) {
                        //@todo фиксим пустой массив значений (пустое значение в SQL-функции IN)
                        if (count($value) == 0) {
                            unset($where[$key]);
                        }
                    }

                    if (isInt($key)) {
                        $select->where($value);
                    } else {
                        if ($alias) {
                            $key = $alias . '.' . $key;
                        }
                        $select->where($key, $value);
                    }
                }
            }

            if ($order !== null) {
                $this->_order($select, $order);
            }

            if ($count !== null || $offset !== null) {
                $select->limit($count, $offset);
            }
        } else {
            $select = $where;
        }

        return $select;
    }

    function select($withFromPart = self::SELECT_WITHOUT_FROM_PART)
    {
        $select = new Workset_Db_Table_Select($this);
        if ($withFromPart == self::SELECT_WITH_FROM_PART) {
            $select->from($this->info(self::NAME), Zend_Db_Table_Select::SQL_WILDCARD, $this->info(self::SCHEMA));
        }
        return $select;
    }

	protected function _groupWhere(array $where, $or = false) {

		$select = $this->select(false);

		foreach ($where as $key => $value) {
			if (isInt($key)) {
				$or ? $select->orWhere($value) : $select->where($value);
			} else {
				$or ? $select->orWhere($key, $value) : $select->where($key, $value);
			}
		}

		$res = $select->getPart(Zend_Db_Select::SQL_WHERE);

		return implode(" ", $res);
	}

}

?>